package cz.muni.dao;

import cz.muni.entities.Courier;
import cz.muni.entities.Shipment;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Ondrej Sotolar
 */
@Stateless
public class ShipmentDao implements ShipmentDaoLocal {

    @PersistenceContext
    private EntityManager em;
    
    public ShipmentDao () {
    }


         /**
     * Insert object into the DB Table
     * 
     * @param  Shipment we want to insert into the DB
     * @return inserted object or null if something went wrong
     * @exception "Wrong Class" exception, when we are trying to insert object into the wrong table
     * e.g. we created Shipment object and we are inserting it into the Tarrif table
     */
    @Override
    public void create(Shipment s) {
        if (s==null) {
            return;
        }
        //EntityManager em = this.emf.createEntityManager();
        em.persist(s);
    }

     /**
     * Delete object from DB
     * 
     * @param Shipment object we want to remove from DB
     * @exception "Object was not found" when we are trying to remove object that
     * does not exist in DB
     */
    @Override
    public void delete(final Shipment t) {
        if (t==null) {
            return;
        }
        //EntityManager em = this.emf.createEntityManager();
        em.remove(em.merge(t));
    }

    /**
     * Find shipment in DB by Long id
     * 
     * @param id id of object we want to find
     * @return object or null
     */
    @Override
    public Shipment find(Long id) {
        if (id==null) {
            return null;
        }
        final Long lid = (id instanceof Long) ? (Long)id : null; 
        //EntityManager em = this.emf.createEntityManager();
        Shipment result = null;
        try {
            result = em.merge(em.find(Shipment.class, lid));
        } catch (IllegalArgumentException e) {
            // should be sht here
        } finally {
            return result;
        }
    }

    /**
     * Update shipment in DB
     * 
     * @param Shipment to be updated
     * @return Updated shipment or null if object is not stored in DB
     */
    @Override
    public Shipment update(final Shipment t) {
        if (t==null) {
            return null;
        }
        //EntityManager em = this.emf.createEntityManager();
        Shipment result =  em.merge(t);
        return result;
    }

    /**
     * Find all Shipments
     * 
     * @return list of all Shipments
     */
    @Override
    public List<Shipment> findAll() {
        //EntityManager em = this.emf.createEntityManager();
        List<Shipment> result = em.createQuery("from " + Shipment.class.getName(), Shipment.class).getResultList();
        return result;
    }

    /**
     * Find all Shipments in entred state
     * 
     * @param state find only shipments is this state
     * @return list of Shipments in entred state or null
     */
    @Override
    public List<Shipment> findByState(final String state) {
        if (isEmpty(state)) { return null; }
        //EntityManager em = this.emf.createEntityManager();
                String query = "from Shipment s where s.shipmentState = '" + state + "'";
         List<Shipment> result = em.createQuery(query, Shipment.class).getResultList();
        return result;
    }

    /**
     * Find all Shipments with selected state and courier. Both can be null.
     * 
     * @param state find only shipments in this state
     * @param courier find only shipments with this courier
     * @return list of Shipments in entred state with selected courier
     */
    @Override
    public List<Shipment> findByStateAndCourier(final String state, final Courier courier) {
        String baseQuery = "from Shipment s ";
        String cid = null;
        String s = null;
        
        if (state != null && !state.equals("")) {
            s = " s.shipmentState = '" + state + "'";
        }
        
        if (courier != null ) { 
            if (courier.getId() != null ) {
                cid = " s.courier=" + courier.getId().toString() + " ";
            }
        }

        if (cid != null || s != null) {
            baseQuery += " where ";
            if (s != null) {
                baseQuery += s;
            }
                else {
                baseQuery += cid;
            }
            if (cid != null) {
                baseQuery += " and " + cid;
            }
        }
        final String query = baseQuery;
        
        //EntityManager em = this.emf.createEntityManager();
        List<Shipment> result =  em.createQuery(query, Shipment.class).getResultList();
        return result;
    }

    /**
     * Find Shipment with entred tracking number. Logs if there are more(and return null).
     * 
     * @param number find only shipments with this tracking number
     * @return list of Shipments in entred state or null
     */
    @Override
        public Shipment findByTrackingNumber(final Long number) {
        if (number==null) {
                return null;
            } 
        //EntityManager em = this.emf.createEntityManager();
                String query = "from Shipment s where s.trackingNumber = " + number.toString() + " ";
        List<Shipment> result = em.createQuery(query, Shipment.class).getResultList();
        List<Shipment> l = result;
        if (l != null) {
            if (l.size() > 1) {
                Logger.getLogger(ShipmentDao.class.getName()).log(Level.SEVERE, "Tracking numbers are not unique.");
                System.err.println("Tracking numbers are not unique");
                return null;
            } else if (l.size() > 0) {
                return l.get(0);
            }
        }
        return null;
    }
    
    private boolean isEmpty(String s) {
        return (s == null || s.equals(""));
    }
}
